package comparesions

import (
	"gvm/instructions/base"
	"gvm/rtda"
	"reflect"
	"strings"
)

type CMP[T int32 | int64 | float32 | float64] struct {
	base.NoOperandsInstruction
}

func (self *CMP[T]) nanFlag() uint8 {
	return 0
}

func (self *CMP[T]) Execute(jFrame *rtda.JFrame) {
	stack := jFrame.OperandStack()
	e := reflect.TypeOf(self).Elem().String()
	etype := strings.ReplaceAll(strings.Split(e, "[")[1], "]", "")
	var v1 T
	var v2 T
	switch etype {
	case "int64":
		v2 = T(stack.PopLong())
		v1 = T(stack.PopLong())
		break
	case "int32":
		v2 = T(stack.PopInt())
		v1 = T(stack.PopInt())
		break
	case "float32":
		v2 = T(stack.PopFloat())
		v1 = T(stack.PopFloat())
		break
	case "float64":
		v2 = T(stack.PopDouble())
		v1 = T(stack.PopDouble())
		break
	}
	if v1 > v2 {
		stack.PushInt(1)
	} else if v1 == v2 {
		stack.PushInt(0)
	} else if v1 < v2 {
		stack.PushInt(-1)
	} else if v1 == v2 {
		stack.PushInt(0)
	} else {
		if self.nanFlag() != 0 {
			if self.nanFlag() == 1 {
				stack.PushInt(1)
			} else {
				stack.PushInt(0)
			}
		}
	}
}

type LCMP struct {
	CMP[int64]
}

type DCMP struct {
	CMP[int64]
	NanFlag uint8
}
type FCMP struct {
	CMP[int64]
	NanFlag uint8
}

func (self *DCMP) nanFlag() uint8 {
	return self.NanFlag
}
func (self *FCMP) nanFlag() uint8 {
	return self.NanFlag
}
